import { _decorator, Camera, CapsuleCollider, Collider, color, Component, director, EventTouch, geometry, instantiate, JsonAsset, MeshRenderer, Node, Prefab, Quat, resources, RigidBody, Scene, Sprite, tween, UIOpacity, v2, v3, Vec2, Vec3, view } from 'cc';
import { EventController, MyEvent } from './Controller/EventController';

import { UIManager } from './UIManager';
import { NavMesh } from './Nav/NavMesh';
import { NPCController } from './Controller/NPCController';
import { PlayerController } from './Controller/PlayerController';
import { Builder } from './Nav/Builder';
import { AudioManager } from './AudioManager';
import { EventManager, IncidentEvent } from './EventManager';
import { taskPanel } from './UI/taskPanel';
import Banner from './Banner';
import { ProjectEvent, ProjectEventManager } from './ProjectEventManager';

const { ccclass, property } = _decorator;
const _vector1 = /*@__PURE__*/ new Vec3();
const _vector2 = /*@__PURE__*/ new Vec3();


export interface WalkNode {
    Path: Vec3[];
    IsOnPathWalkMove: boolean;

}

@ccclass('GameManager')
export class GameManager extends Component {
    @property(Node)
    PlayerNode: Node = null;
    @property(Node)
    FatherNode: Node = null;
    @property(Node)
    DogNode: Node = null;
    @property(Node)
    UICanvas: Node = null;
    @property(Node)
    Nd: Node = null;
    @property(JsonAsset)
    MapJson: JsonAsset = null;
    @property(MeshRenderer)
    nav: MeshRenderer = null;
    @property(Camera)
    camera: Camera = null;

    ray: geometry.Ray = null;
    public ScreenCenter: Vec2 = v2(2340, 1080);
    public GameOver: boolean = false;
    public GamePause: boolean = false;//游戏暂停
    public Scene: Scene = null;
    public IsFly: boolean = false;
    public aimType: number = 0;
    public aimPosition: Vec3 = null;
    public PlayerIsdanger: boolean = false;//婴儿是否危险
    public PlayerID: number = 0;//0默认婴儿1.插树枝2.坠地哭3.头顶便便4.变蛋糕5,戴圣诞帽6.狮子头7.墨水8.马桶搋子9.灭火器喷的全身都是

    public UIIsLook: boolean = true;//UI可视
    public rideid: number = -1;//乘坐按钮id，0秋千1小车，-1表示没坐骑，2小黄鸭3木马
    public PlayerIsOnsteer: boolean = false; //玩家是否驾驶中
    public PlayerIsOndilemma: boolean = false;//玩家是否陷入困难
    public PlayerIsOnDogBox: boolean = false;//玩家是否在狗区
    public interactionNode: string = "";//当前交互对象
    public Taskschedule: boolean[] = [false, false, false, false, false, false, false, false, false, false, false, false,
        false, false, false, false];//任务是否完成

    public MapId: string = null;
    private _path = [];
    distance: number = 0;
    private targetPos = new Vec3();

    public CD: number[] = [0, 0];//CD:0跳跃CD1翻滚技能CD
    public CDMAX: number[] = [2, 15];//CD最大值

    public Fatheranger: number = 0;//父亲的怒气


    private JumpCdMask: Node = null;
    private AddSpeedCdMask: Node = null;
    private static _instance: GameManager = null;
    public static get Instance(): GameManager {
        if (!this._instance) {
            this._instance = new GameManager();
        }
        return this._instance;
    }
    protected onLoad(): void {
        GameManager._instance = this;
        this.ScreenCenter = v2(view.getViewportRect().width / 2, view.getViewportRect().height / 2);
        this.Scene = director.getScene();
        this.UICanvas.getChildByPath("右下角UI块/跳跃").on(Node.EventType.TOUCH_START, this.OnJumpClick, this);
        this.UICanvas.getChildByPath("右下角UI块/跳跃").on(Node.EventType.TOUCH_END, this.OnJumpEndClick, this);
        this.UICanvas.getChildByPath("右下角UI块/跳跃").on(Node.EventType.TOUCH_CANCEL, this.OnJumpEndClick, this);
        let MapNodes = Builder.buildZoneByJson(this.MapJson.json);
        this.MapId = this.MapJson.name;
        NavMesh.setZoneData(this.MapId, MapNodes);
    }
    protected update(dt: number): void {
        for (let i = 0; i < this.CD.length; i++) {
            if (this.CD[i] > 0) {
                this.CD[i] -= dt;
            }

        }
        this.UIShow();
    }
    private _PlayerScale: Vec3 = null;
    private _Playerrotation: Quat = null;
    start() {
        this._PlayerScale = this.PlayerNode.worldScale.clone();
        this._Playerrotation = this.PlayerNode.worldRotation.clone();
        this.JumpCdMask = this.UICanvas.getChildByPath("右下角UI块/跳跃/遮罩");
        this.AddSpeedCdMask = this.UICanvas.getChildByPath("右下角UI块/翻滚/遮罩");
        AudioManager.playLookAudio("BGM");
        EventManager.on(IncidentEvent.OverTask, this.OverTask, this);
        this.UICanvas.getChildByName("任务界面").getComponent(taskPanel).Show();
        this.UICanvas.getChildByName("新手教程界面").active = true;

        ProjectEventManager.emit(ProjectEvent.游戏开始);
    }
    //完成任务
    OverTask(index: number) {
        if (GameManager.Instance.Taskschedule[index] == true) {
            return;
        }
        this.Taskschedule[index] = true;
        UIManager.HopHint("任务" + (index + 1) + "完成！", 2, v3(-900, 230, 0), v3(0, 100, 0));
        let isWInner: boolean = true;
        this.Taskschedule.forEach(cd => {
            if (cd == false) isWInner = false;
        });
        if (isWInner) {
            this.gameOver(isWInner);
        }
    }
    UIShow() {
        if (this.CD[0] <= 0) {
            this.JumpCdMask.active = false;
        } else {
            this.JumpCdMask.active = true;
            this.JumpCdMask.getComponent(Sprite).fillRange = this.CD[0] / this.CDMAX[0];
        }

        if (this.CD[1] <= 0) {
            this.AddSpeedCdMask.active = false;
        } else {
            this.AddSpeedCdMask.active = true;
            this.AddSpeedCdMask.getComponent(Sprite).fillRange = this.CD[1] / this.CDMAX[1];
        }
    }

    //按下跳跃
    OnJumpClick() {
        GameManager.Instance.Scene.emit(MyEvent.JUMP);
        this.CD[0] = this.CDMAX[0];
        this.IsFly = true;
    }
    //跳跃结束
    OnJumpEndClick() {
        this.IsFly = false;
    }


    //按钮事件
    OnButtonClick(btn: EventTouch) {
        switch (btn.target.name) {
            case "扑":
                this.inOutdilemma(true);
                break;
            case "翻滚":
                this.CD[1] = this.CDMAX[1];
                this.PlayerNode.getComponent(PlayerController).AddUpSpeedTime(2, 5);
                break;
            case "返回":
                AudioManager.AudioPlay("按钮点击", 0);
                this.UICanvas.getChildByName("返回菜单").active = true;
                ProjectEventManager.emit(ProjectEvent.弹出窗口);
                break;
            case "复位":
                AudioManager.AudioPlay("按钮点击", 0);
                this.UICanvas.getChildByPath("左上角UI块/复位").active = false;
                this.PlayerNode.setWorldPosition(0, 2, 3);
                this.scheduleOnce(() => {
                    this.UICanvas.getChildByPath("左上角UI块/复位").active = true;
                }, 3)
                break;
            case "返回主页":
            case "成功界面":
            case "失败界面":
                this.ReturnMain();
                break;
            case "继续游戏":
                AudioManager.AudioPlay("按钮点击", 0);
                this.UICanvas.getChildByName("返回菜单").active = false;
                break;
            case "交互":
                this.OninteractionClick();
                break;
            case "任务":
                AudioManager.AudioPlay("按钮点击", 0);
                ProjectEventManager.emit(ProjectEvent.弹出窗口);
                this.UICanvas.getChildByName("任务界面").active = true;
                break;
            case "教程按钮":
                AudioManager.AudioPlay("按钮点击", 0);
                this.UICanvas.getChildByName("新手教程界面").active = true;
                break;
            case "减怒气":
                AudioManager.AudioPlay("按钮点击", 0);
                Banner.Instance.ShowVideoAd(() => {
                    this.AddFatheranger(-100);
                    UIManager.HopHint("爸爸消消气！！！");
                })
                break;
        }
    }



    FatherFind() {
        this.FindPath(this.targetPos, this.FatherNode);//寻路
    }
    DogFind() {
        this.FindPath(this.targetPos, this.DogNode);//寻路
    }
    /**
     * 
     * @param pos 目标位置
     * @param nd 需要计算路径的单位
     */
    FindPath(pos: Vec3, nd: Node) {

        nd.getComponent(NPCController).Path = [];
        nd.getComponent(NPCController).Path = this.findPath(this.MapId, nd.position, pos);
        if (nd.getComponent(NPCController).Path == null || nd.getComponent(NPCController).Path.length == 0) {
            UIManager.HopHint("当前位置爸爸找不到你，请离开或者按左上角第二个按钮复位！", 2);
            return;
        }
        this.Nd.getChildByName("小盒子").children.forEach(pre => { pre.destroy(); })
        //寻路中添加白色小块
        // nd.getComponent(NPCController).Path.forEach(element => {
        //     this.InstanceNode("Prefab/盒子", element, this.Nd.getChildByName("小盒子"));
        // });
        nd.getComponent(NPCController).IsOnPathWalkMove = true;
    }

    /**
     * 查找从起点到终点的导航路径
     * @param zoneID 区域ID，用于标识导航网格区域
     * @param pos 起点位置坐标
     * @param des 终点位置坐标
     * @returns 返回路径点数组
     */
    findPath(zoneID: string, pos: Vec3, des: Vec3): any[] {
        // 获取玩家当前位置并创建向下射线
        let playerpos = this.PlayerNode.getWorldPosition();
        this.ray = new geometry.Ray(playerpos.x, playerpos.y, playerpos.z, 0, -1, 0);
        this.distance = Number.MAX_VALUE;

        // 执行射线检测，获取与导航网格的交点距离
        const dis = geometry.intersect.rayModel(this.ray, this.nav.model, { mode: geometry.ERaycastMode.CLOSEST, doubleSided: false, distance: 2 });
        if (dis && dis < Number.MAX_VALUE) {
            this.distance = dis;
        }

        // 计算射线击中点位置
        this.ray.computeHit(this.targetPos, this.distance);

        // 获取起点所在的导航网格组ID
        _vector1.set(pos);
        const groupId = NavMesh.getGroup(zoneID, _vector1);

        // 计算从起点到终点的导航路径
        _vector2.set(des);
        const path = NavMesh.findPath(_vector1, _vector2, zoneID, groupId);

        return path;
    }
    //重新开始游戏
    ReStarGame() {
        UIManager.GoScene("Game");
    }
    //返回主页
    ReturnMain() {
        AudioManager.AudioPlay("按钮点击", 0);
        AudioManager.StopLoopAudio("BGM");
        AudioManager.StopLoopAudio("婴儿哭");
        UIManager.GoScene("MainPanel");
        ProjectEventManager.emit(ProjectEvent.返回主页);
    }





    //生成物体
    InstanceNode(path: string, pos: Vec3, parent: Node = this.Nd, offset: Vec3 = v3(0, 0, 0)) {
        resources.load(path, Prefab, (err, event) => {
            let pre = instantiate(event);
            pre.setParent(parent);
            pre.setWorldPosition(pos.clone().add(offset))
        })
    }

    //切换人物状态
    SetPlayer(id: number) {
        this.PlayerID = id;
        let index: number = 0;
        while (this.PlayerNode.getChildByPath("PlayerModel/PlayerModel" + index)) {
            this.PlayerNode.getChildByPath("PlayerModel/PlayerModel" + index).active = false;
            index++;
        }
        this.PlayerNode.getComponent(PlayerController)._PlayerModel = this.PlayerNode.getChildByPath("PlayerModel/PlayerModel" + id);
        this.PlayerNode.getChildByPath("PlayerModel/PlayerModel" + id).active = true;
        this.PlayerNode.getComponent(PlayerController)._Ani = "";
    }

    //切换UI可视状态
    ChangGeUI(id: number) {
        switch (id) {
            case 0://正常
                this.UICanvas.getChildByPath("Joystick/JoystickArea").active = true;
                this.UICanvas.getChildByPath("Joystick/JoystickBase").active = true;
                this.UICanvas.getChildByName("右下角UI块").active = true;
                this.UICanvas.getChildByName("离开").active = false;
                this.UIIsLook = true;
                break;
            case 1://乘骑
                GameManager.Instance.Scene.emit(MyEvent.MOVEMENT_STOP)//移动停止
                this.UICanvas.getChildByPath("Joystick/JoystickArea").active = false;
                this.UICanvas.getChildByPath("Joystick/JoystickBase").active = false;
                this.UICanvas.getChildByName("右下角UI块").active = false;
                this.UICanvas.getChildByName("离开").active = true;
                this.UIIsLook = false;
                break;
            case 2://可移动乘骑
                GameManager.Instance.Scene.emit(MyEvent.MOVEMENT_STOP)//移动停止
                this.UICanvas.getChildByName("右下角UI块").active = false;
                this.UICanvas.getChildByName("离开").active = true;
                this.UIIsLook = false;
                break;
            case 3://陷入困境
                GameManager.Instance.Scene.emit(MyEvent.MOVEMENT_STOP)//移动停止
                this.UICanvas.getChildByPath("Joystick/JoystickArea").active = false;
                this.UICanvas.getChildByPath("Joystick/JoystickBase").active = false;
                this.UICanvas.getChildByName("右下角UI块").active = false;
                this.UIIsLook = false;
                break;
        }

    }


    //点击乘坐按钮
    OnrideClick() {
        if (this.PlayerIsOndilemma) {
            UIManager.HopHint("当前不可操作！");
            return;
        }

        this.UICanvas.getChildByName("乘坐").active = false;
        this.PlayerIsOnsteer = true;
        switch (this.rideid) {
            case 0://荡秋千
                this.ChangGeUI(1);
                this.UICanvas.getChildByName("离开").active = false;
                this.Nd.getChildByPath("触发物/秋千/模型/左椅子/Player").active = true;
                this.Nd.getChildByPath("触发物/秋千/Camera").active = true;
                this.PlayerNode.active = false;
                tween(this.Nd.getChildByPath("触发物/秋千/模型/左椅子"))
                    .to(2, { eulerAngles: v3(0, 0, 180) })
                    .call(() => {
                        this.Nd.getChildByPath("触发物/秋千/模型/左椅子/Player").active = false;
                        this.PlayerNode.active = true;
                        this.Nd.getChildByPath("触发物/秋千/Camera").active = false;
                        this.PlayerNode.setWorldPosition(this.Nd.getChildByPath("触发物/秋千/模型/左椅子/Player").getWorldPosition());
                        //换成草人
                        this.SetPlayer(1);
                        this.inOutdilemma(true);
                        this.PlayerIsOnsteer = false;
                        EventManager.Emit(IncidentEvent.OverTask, 5);
                    })
                    .to(2, { eulerAngles: v3(0, 0, 0) })
                    .start();
                break;
            case 1://小车
                this.ChangGeUI(2);
                this.PlayerNode.getChildByPath("PlayerModel/载具/小车").active = true;
                this.Nd.getChildByPath("触发物/小车").active = false;
                this.PlayerNode.getComponent(CapsuleCollider).radius = 0.4;
                EventManager.Emit(IncidentEvent.OverTask, 3);
                break;
            case 2://小黄鸭
                this.ChangGeUI(1);
                EventManager.Emit(IncidentEvent.OverTask, 2);
                this.PlayerNode.getComponent(RigidBody).enabled = false;
                this.PlayerNode.getComponent(Collider).enabled = false;
                this.PlayerNode.setParent(this.Nd.getChildByPath("触发物/小黄鸭/Bone.025 Socket"));
                this.ReSetPlayerNodeState();
                this.PlayerNode.setPosition(v3(0, 0, -0.005));
                this.PlayerNode.getComponent(PlayerController)._PlayerModel.parent.eulerAngles = v3(0, this.Nd.getChildByPath("触发物/小黄鸭").eulerAngles.y == 0 ? 0 : 180, 0);
                break;
            case 3://木马
                EventManager.Emit(IncidentEvent.OverTask, 15);
                this.ChangGeUI(1);
                this.PlayerNode.getComponent(RigidBody).enabled = false;
                this.PlayerNode.getComponent(Collider).enabled = false;
                this.PlayerNode.setParent(this.Nd.getChildByPath("触发物/木马/muma/Horse_end Socket"));
                this.ReSetPlayerNodeState();
                this.PlayerNode.setPosition(v3(0, 0.022, -0.005));
                this.PlayerNode.getComponent(PlayerController)._PlayerModel.parent.eulerAngles = v3(0, this.Nd.getChildByPath("触发物/木马").eulerAngles.y == 0 ? 0 : 180, 0);
                break;
        }
    }
    //点击离开乘坐按钮
    OnExitrideClick() {
        if (this.PlayerIsOndilemma) {
            UIManager.HopHint("当前不可操作！");
            return;
        }
        this.UICanvas.getChildByName("离开").active = false;
        this.ChangGeUI(0);
        switch (this.rideid) {
            case 0://荡秋千
                this.PlayerNode.active = true;
                break;
            case 1://小车
                this.PlayerNode.getComponent(CapsuleCollider).radius = 0.2;
                this.PlayerNode.getChildByPath("PlayerModel/载具/小车").active = false;
                this.Nd.getChildByPath("触发物/小车").active = true;
                this.Nd.getChildByPath("触发物/小车").setWorldPosition(this.PlayerNode.getWorldPosition().subtract(v3(0, 0.2, 0)));
                break;
            case 2://小黄鸭
                this.PlayerNode.setParent(this.Nd);
                this.PlayerNode.setWorldPosition(this.Nd.getChildByPath("触发物/小黄鸭").getWorldPosition().add(v3(0.3, 0.4, 0)));
                this.PlayerNode.getComponent(RigidBody).enabled = true;
                this.PlayerNode.getComponent(Collider).enabled = true;
                this.ReSetPlayerNodeState();
                break;
            case 3://木马
                this.PlayerNode.setParent(this.Nd);
                this.PlayerNode.setWorldPosition(this.Nd.getChildByPath("触发物/木马").getWorldPosition().add(v3(0.3, 0.4, 0)));
                this.PlayerNode.getComponent(RigidBody).enabled = true;
                this.PlayerNode.getComponent(Collider).enabled = true;
                this.ReSetPlayerNodeState();
                break;
        }
        this.rideid = -1;
        this.PlayerIsOnsteer = false;
    }

    //点击交互按钮
    OninteractionClick() {
        if (this.PlayerIsOndilemma) {
            UIManager.HopHint("当前不可操作！");
            return;
        }

        switch (this.interactionNode) {
            case "蛋糕":
                this.SetPlayer(4);
                this.inOutdilemma(true, "变成蛋糕了！等待爸爸来救我");
                this.ChangGeUI(0);
                this.Nd.getChildByPath("触发物/蛋糕").active = false;
                EventManager.Emit(IncidentEvent.OverTask, 12);
                break;
            case "圣诞帽":
                this.SetPlayer(5);
                this.Nd.getChildByPath("触发物/圣诞帽").active = false;
                EventManager.Emit(IncidentEvent.OverTask, 14);
                break;
            case "狮子头":
                this.SetPlayer(6);
                this.Nd.getChildByPath("触发物/狮子头").active = false;
                EventManager.Emit(IncidentEvent.OverTask, 13);
                break;
            case "墨水瓶":
                this.SetPlayer(7);
                this.inOutdilemma(true, "浑身都脏了!等爸爸来清理");
                this.Nd.getChildByPath("触发物/墨水瓶").active = false;
                EventManager.Emit(IncidentEvent.OverTask, 1);
                break;
            case "马桶搋子":
                this.SetPlayer(8);
                this.inOutdilemma(true, "马桶搋子吸在头上了，让爸爸把它取下来！");
                this.Nd.getChildByPath("触发物/马桶搋子").active = false;
                EventManager.Emit(IncidentEvent.OverTask, 9);
                break;
            case "灭火器":
                this.SetPlayer(9);
                resources.load("Prefab/烟雾", Prefab, (err, data) => {
                    let pre = instantiate(data);
                    pre.setParent(this.Nd);
                    pre.setWorldPosition(this.Nd.getChildByPath("触发物/灭火器").getWorldPosition());
                    this.scheduleOnce(() => {
                        pre.destroy();
                    }, 3)
                })
                this.inOutdilemma(true, "粉末一身都是！等爸爸来擦干净");
                this.ChangGeUI(0);
                EventManager.Emit(IncidentEvent.OverTask, 7);
                break;
            case "辣椒":
                this.SetPlayer(10);
                this.inOutdilemma(true, "好辣！！！");
                this.Nd.getChildByPath("触发物/辣椒").active = false;
                this.ChangGeUI(0);
                EventManager.Emit(IncidentEvent.OverTask, 11);
                break;
            case "垃圾桶":
                this.SetPlayer(11);
                this.inOutdilemma(true, "被垃圾袋裹住了！等爸爸来帮忙");
                EventManager.Emit(IncidentEvent.OverTask, 6);
                break;
        }
    }


    //将人物恢复至默认状态大小
    ReSetPlayerNodeState() {
        this.PlayerNode.setWorldScale(this._PlayerScale);
        this.PlayerNode.setWorldRotation(this._Playerrotation);
    }

    //玩家陷入困境
    inOutdilemma(isin: boolean, text: string = "陷入危险中，等待爸爸救援！") {
        this.PlayerIsOndilemma = isin;
        if (isin) {
            this.ChangGeUI(3);
            UIManager.HopHint(text);
            AudioManager.playLookAudio("婴儿哭");
            this.UICanvas.getChildByName("提示").active = true;
        } else {
            this.ChangGeUI(0);
            this.SetPlayer(0);
            UIManager.HopHint("爸爸生气了");
            this.AddFatheranger(10);
            AudioManager.StopLoopAudio("婴儿哭");
            this.UICanvas.getChildByName("提示").active = false;
        }
    }
    //玩家被狗搞哭
    bulliedbydog() {
        UIManager.HopHint("狗狗离我远点！！！");
    }
    //增加父亲的怒气值
    AddFatheranger(num: number) {
        this.Fatheranger += num;
        if (this.Fatheranger < 0) this.Fatheranger = 0;
        tween(this.UICanvas.getChildByPath("生气界面/怒气条/进度条顶部").getComponent(Sprite))
            .to(0.5, { fillRange: this.Fatheranger / 100 })
            .start();
        if (this.Fatheranger >= 60) {
            this.UICanvas.getChildByPath("生气界面/怒气条/进度条顶部").getComponent(Sprite).color = color(255, 105, 46);
        }
        if (this.Fatheranger >= 80) {
            this.UICanvas.getChildByPath("生气界面/怒气条/进度条顶部").getComponent(Sprite).color = color(255, 0, 0);
        }
        if (this.Fatheranger >= 100) {
            this.gameOver(false);
        }
    }

    gameOver(isWinner: boolean) {
        let pre = this.UICanvas.getChildByName("结算界面");
        pre.active = true;
        tween(pre.getChildByName("Mask").getComponent(UIOpacity))
            .to(1, { opacity: 255 })
            .call(() => {
                if (isWinner) {
                    pre.getChildByName("成功界面").active = true;
                } else {
                    pre.getChildByName("失败界面").active = true;
                }
                pre.getChildByName("Tip").active = true;
                ProjectEventManager.emit(ProjectEvent.游戏结束);
            })
            .to(1, { opacity: 0 })
            .start();
    }
}


